import axios, { type AxiosInstance, type AxiosInterceptorOptions, type AxiosRequestConfig, type AxiosResponse, type CreateAxiosDefaults, type InternalAxiosRequestConfig } from 'axios';




const REQ_INTC = <V = InternalAxiosRequestConfig<any>>(onFulfilled?: ((value: V) => V | Promise<V>) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions) => {
    return (target: any) => {
        if (!target._instance) {
            return;
        }
        const instance = target._instance;
        instance.interceptors.request.use(onFulfilled, onRejected, options);
    };

}

const RES_INTC = <V = AxiosResponse<any, any>>(onFulfilled?: ((value: V) => V | Promise<V>) | null, onRejected?: ((error: any) => any) | null, options?: AxiosInterceptorOptions) => {
    return (target: any) => {
        if (!target._instance) {
            return;
        }
        const instance = target._instance;
        instance.interceptors.response.use(onFulfilled, onRejected, options);
    };

}

const HTTP = (config?: CreateAxiosDefaults<any>) => {
    return (target: any) => {
        const instance = axios.create(config);
        target._instance = instance;
    }
}





const REQUEST = (method: string) => {
    const isGet = method == 'get';
    return (url: string, config?: AxiosRequestConfig) => {
        return (target: any, key: string) => {
            const execute = (params?: any, config2?: AxiosRequestConfig) => {
                config = {
                    ...config,
                    ...config2
                };
                const instance: AxiosInstance = target._instance;

                return instance.request({
                    ...config,
                    method,
                    url,
                    params: isGet ? params : null,
                    data: !isGet ? params : null,
                });

            }
            target[key] = execute;
        }
    }
}


const GET = REQUEST('get');
const POST = REQUEST('post');
const DELETE = REQUEST('delete');
const PUT = REQUEST('put');

interface Execute<T = any, R = any> {
    (value?: T, config?: AxiosRequestConfig): Promise<AxiosResponse<R>>;
}

export { GET, POST, DELETE, PUT, REQ_INTC, RES_INTC, HTTP, type Execute }

